package com.fit.utils.se;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import java.net.URL;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.net.ssl.SSLException;
import javax.net.ssl.SSLHandshakeException;

import org.apache.http.Consts;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpRequest;
import org.apache.http.NameValuePair;
import org.apache.http.NoHttpResponseException;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.config.RequestConfig.Builder;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.HttpClientConnectionManager;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.CharsetUtils;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * 发送http请求工具
 * 
 * @author Administrator
 * httpclient-4.5.3.jar、httpclient-cache-4.5.3.jar、httpcore-4.4.6.jar、httpmime-4.5.3.jar
 * 
 */
public class HttpClientUtil {

	private static Logger log = LoggerFactory.getLogger(HttpClientUtil.class);
	
	/**
	 * 最大连接数
	 */
	private final static int MAX_TOTAL_CONNECTIONS = 20;
	
	 /** 
     * 每个路由最大连接数 
     */  
	private final static int MAX_ROUTE_CONNECTIONS = 40;
   
    /** 
     * 获取连接超时
     */  
	private final static int CONNECT_TIMEOUT = 200000; 
	
	 /** 
     * 连接请求超时5分钟
     */  
	private final static int WAIT_TIMEOUT = 900000;  
	
    /** 
     * 获取连接的最大等待时间 
     */  
	private final static int CONNECT_REQUEST_TIMEOUT = 160000;  
    
    /**
     * 请求失败，重新请求次数
     */
	private final static int RETRY_REQUEST_NUM = 3;
    
	
	/**
	 * 请求方式
	 */
	private final static String GET = "GET";
	private final static String POST = "POST";
	
	
	
	/**
	 * httpClient连接池
	 */
	private static PoolingHttpClientConnectionManager pool;
	
	
	
	/**
	 * 创建HTTPClient连接池
	 * @param plainsf
	 * @param sslsf
	 * @return
	 */
	public static PoolingHttpClientConnectionManager createHttpClientPool(ConnectionSocketFactory plainsf, LayeredConnectionSocketFactory sslsf){
		RegistryBuilder<ConnectionSocketFactory> registryBuilder = RegistryBuilder.<ConnectionSocketFactory>create();
		if(plainsf != null){
			//支持http
			registryBuilder.register("http", plainsf);
		}
		if(sslsf != null){
			//支持https
			registryBuilder.register("https", sslsf);
		}
		Registry<ConnectionSocketFactory> registry = registryBuilder.build();
		//创建连接池
		return new PoolingHttpClientConnectionManager(registry);
	}
	
	
	
	
	/**
	 * 创建httpClient
	 * @param pool 连接池
	 * @param httpRequestRetryHandler 请求重试处理程序
	 * @return
	 */
	public static CloseableHttpClient createHttpClient(HttpClientConnectionManager pool,HttpRequestRetryHandler httpRequestRetryHandler){
		HttpClientBuilder httpClientBuilder = HttpClients.custom();
		httpClientBuilder.setConnectionManager(pool);
		if(httpRequestRetryHandler != null){
			httpClientBuilder.setRetryHandler(httpRequestRetryHandler);
		}
		return httpClientBuilder.build();
	}
	
	
	
	
	
	
	
	
	/**
	 * 获取HTTPClient连接池(只用于本类)
	 * @return
	 * @throws KeyStoreException 
	 * @throws NoSuchAlgorithmException 
	 * @throws KeyManagementException 
	 */
	private static PoolingHttpClientConnectionManager getHttpClientPool(){
		if(pool == null){
			synchronized (HttpClientUtil.class) {
				if(pool == null){
					pool = HttpClientUtil.createHttpClientPool(PlainConnectionSocketFactory.getSocketFactory(), SSLConnectionSocketFactory.getSocketFactory());
			        //最大连接数
					pool.setMaxTotal(HttpClientUtil.MAX_TOTAL_CONNECTIONS);
					//每个路由最大连接数 
					pool.setDefaultMaxPerRoute(HttpClientUtil.MAX_ROUTE_CONNECTIONS);
					// 将目标主机的最大连接数增加到50
			        //HttpHost localhost = new HttpHost("http://blog.csdn.net/gaolu",80);
			        //pool.setMaxPerRoute(new HttpRoute(localhost), 50);
				}
			}
		}
		return pool;
	}
	
	
	
	/**
	 * 获取httpClient(只用于本类)
	 * @return
	 */
	private static CloseableHttpClient getHttpClient(){
		//请求重试处理
        HttpRequestRetryHandler httpRequestRetryHandler = new HttpRequestRetryHandler() {
        	@Override
            public boolean retryRequest(IOException exception,int executionCount, HttpContext context) {
                if (executionCount > HttpClientUtil.RETRY_REQUEST_NUM) {// 如果已经重试超过3次，就放弃，可以配置
                    return false;
                }
                if (exception instanceof NoHttpResponseException) {// 如果服务器丢掉了连接，那么就重试                    
                    return true;
                }
                if (exception instanceof SSLHandshakeException) {// 不要重试SSL握手异常                    
                    return false;
                }                
                if (exception instanceof InterruptedIOException) {// 超时                    
                    return false;
                }
                if (exception instanceof UnknownHostException) {// 目标服务器不可达                    
                    return true;
                }
                if (exception instanceof ConnectTimeoutException) {// 连接被拒绝                    
                    return false;
                }
                if (exception instanceof SSLException) {// ssl握手异常                    
                    return false;
                }
                HttpClientContext clientContext = HttpClientContext.adapt(context);
                HttpRequest request = clientContext.getRequest();
                // 如果请求是幂等的，就再次尝试
                if (!(request instanceof HttpEntityEnclosingRequest)) {                    
                    return true;
                }
                return false;
            }
        };  
        return HttpClientUtil.createHttpClient(HttpClientUtil.getHttpClientPool(), httpRequestRetryHandler);
	}
	
	


	/**
	 * 基础的发送请求（本类使用）
	 * @param httpClient 【必须的】
	 * @param url 【必须的】
	 * @param requestMode 请求方式(POST或GET) 【必须的】
	 * @param headMap 请求头      
	 * @param paraMap 请求参数  [如果设置了paraMap,就不能设置paraBody]
	 * @param paraBody 请求体[如果设置了paraBody,就不能设置其他参数了，如paraMap和fileMap(paraMap和fileMap优先级更高)]  【get方式不支持】    
	 * @param requestConfig 请求配置
	 * @param fileMap  上传的文件[如果设置了此参数fileMap,就不能设置paraBody] 【get方式不支持】 
	 * @param charset  字符编码
	 * @return byte数组
	 */
	private static byte[] basicSend(CloseableHttpClient httpClient,String url,
								String requestMode,
								Map<String,String> headMap, 
								Map<String, String> paraMap,
								String paraBody,
								RequestConfig requestConfig,
								Map<String,File> fileMap,
								String charset) throws Exception{
		byte[] resultByte = null;
		HttpRequestBase httpConn = null;
		try{
			//设置默认的headMap

			requestMode = requestMode.toUpperCase();
			if(charset == null || charset.trim().equals("")){
				charset = "UTF-8";
			}
			charset = charset.trim(); url = url.trim();
			
			if(GET.equals(requestMode)){
				/**
				 * get方式
				 */
				String para = "";
				if(paraMap != null && paraMap.size() > 0){
					// 拼接参数
					Iterator<Entry<String, String>> iterator = paraMap.entrySet().iterator();
					List<NameValuePair> params = new LinkedList<NameValuePair>();
					while (iterator.hasNext()) {
						Entry<String, String> elem = (Entry<String, String>) iterator.next();
				        params.add(new BasicNameValuePair(elem.getKey(), elem.getValue()));
					}
					para = "?"+EntityUtils.toString(new UrlEncodedFormEntity(params, Consts.UTF_8));
				}
				
				
				
				httpConn = new HttpGet(url + para);
			}else{
				/**
				 * post方式	
				 */
				httpConn = new HttpPost(url);
				
				if(fileMap != null && fileMap.size() > 0){
					//上传文件
					MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create()  
                    .setMode(HttpMultipartMode.BROWSER_COMPATIBLE); // 以浏览器兼容模式运行，防止文件名乱码。
					Iterator<Entry<String, File>> it = fileMap.entrySet().iterator();
					while(it.hasNext()){
						Entry<String, File> entry = it.next();
						FileBody bin = new FileBody(entry.getValue());
						multipartEntityBuilder.addPart(entry.getKey(), bin);
					}
					// 设置参数
					if(paraMap != null && paraMap.size() > 0){
						
						Iterator<Entry<String, String>> iterator = paraMap.entrySet().iterator();
						while (iterator.hasNext()) {
							Entry<String, String> elem = (Entry<String, String>) iterator.next();
							multipartEntityBuilder.addTextBody(elem.getKey(), new String(elem.getValue().getBytes("UTF-8"),"ISO-8859-1"));
						}
					}
					HttpEntity reqEntity = multipartEntityBuilder.setCharset(CharsetUtils.get(charset)).build();
					((HttpPost)httpConn).setEntity(reqEntity); 
				}else if(paraMap != null && paraMap.size() > 0){
					// 设置参数
					List<NameValuePair> list = new LinkedList<NameValuePair>();
					Iterator<Entry<String, String>> iterator = paraMap.entrySet().iterator();
					while (iterator.hasNext()) {
						Entry<String, String> elem = (Entry<String, String>) iterator.next();
						list.add(new BasicNameValuePair(elem.getKey(), elem.getValue()));
					}
					if (list.size() > 0) {
						UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list,charset);
						((HttpPost)httpConn).setEntity(entity);
					}
				}else if(paraBody != null && !paraBody.trim().equals("")){
					//设置请求内容
					StringEntity stringEntity = new StringEntity(paraBody,charset);//解决中文乱码问题
					stringEntity.setContentEncoding(charset);  
		            ((HttpPost)httpConn).setEntity(stringEntity);
				}
			}
			
			//设置请求头
			if(headMap != null && headMap.size() > 0){
				List<Header> list = new LinkedList<Header>();
				Iterator<Entry<String, String>> headIt = headMap.entrySet().iterator();
				while(headIt.hasNext()){
					Entry<String, String> elem = headIt.next();
					Header header = new BasicHeader(elem.getKey(), elem.getValue());
					list.add(header);
				}
				if (list.size() > 0) {
					Header[] headerArr = new Header[list.size()];
					for(int i=0; i<list.size(); i++){
						headerArr[i] = list.get(i);
					}
					httpConn.setHeaders(headerArr);
				}
			}
			
			//设置请求配置
			if(requestConfig != null){
				httpConn.setConfig(requestConfig);
			}
			CloseableHttpResponse response = httpClient.execute(httpConn);
			if (response != null) {
				
				InputStream in = null;
				ByteArrayOutputStream out = null;
				try{
					if(response.getStatusLine().getStatusCode() == 302 || response.getStatusLine().getStatusCode() == 302){
						
						Header[] header = response.getHeaders("Location");
						String redirectStr = null;
						if(header != null && header.length > 0){
							redirectStr = header[0].getValue();
							if(redirectStr.startsWith("/")){
								URL u = new URL(url);
								String host = "http://"+u.getHost()+":"+u.getPort();// 获取主机名 
								redirectStr = host+redirectStr;
							}
						}
						if(redirectStr != null && !"".equals(redirectStr.trim())){
							//重定向
							resultByte = HttpClientUtil.basicSend(httpClient, redirectStr, requestMode, headMap, paraMap, paraBody, requestConfig, fileMap, charset);
						}
					}else{
						HttpEntity resEntity = response.getEntity();
						//获取输入流
						in = resEntity.getContent();
						out = new ByteArrayOutputStream();
						byte[] b = new byte[512000];//500KB
						int len = -1;
						while((len = in.read(b)) != -1){
							out.write(b, 0, len);
						}
						resultByte = out.toByteArray();
					}
				}finally{
					if(in != null){
						in.close();
					}
					if(out != null){
						out.flush();
						out.close();
					}
					if(response != null){
						response.close();
					}
				}
			}
			if(resultByte == null){
				resultByte = new byte[0];
			}
		}catch(Exception e){
			log.error("发起请求异常",e);
		}finally{
			if(httpConn != null){
				httpConn.releaseConnection();
			}
		}
		return resultByte;
	}
	
	
	
	

	/**
	 * 发送post请求
	 * @param url 目标地址
	 * @param headMap 请求头map
	 * @param paraMap 请求参数map (参数不能同时使用，如：[如果设置了paraBody,就不能设置其他参数了，如paraMap和fileMap(paraMap和fileMap优先级更高)]     )
	 * @param paraBody 请求内容
	 * @param requestConfig 请求配置对象
	 * @param fileMap 上传的文件map 
	 * @param charset 返回结果及请求结果编码
	 * @return
	 * @throws Exception
	 */
	public static byte[] sendPost(String url,Map<String,String> headMap, Map<String, String> paraMap,String paraBody,RequestConfig requestConfig,Map<String, File> fileMap,String charset) throws Exception {
		return HttpClientUtil.basicSend(HttpClientUtil.getHttpClient(), url, HttpClientUtil.POST, headMap, paraMap, paraBody, requestConfig, fileMap, charset);
	}
	
	
	/**
	 * 发送post请求
	 * @param url 目标地址
	 * @param headMap 请求头map
	 * @param paraMap 请求参数map (参数不能同时使用，如：[如果设置了paraBody,就不能设置其他参数了，如paraMap和fileMap(paraMap和fileMap优先级更高)]     )
	 * @param paraBody 请求内容
	 * @param fileMap 上传的文件map 
	 * @param charset 返回结果及请求结果编码
	 * @param waitTimeout 请求超时毫秒
	 * @return
	 * @throws Exception
	 */
	public static byte[] sendPost(String url,Map<String,String> headMap, Map<String, String> paraMap,String paraBody,Map<String, File> fileMap,String charset,Integer waitTimeout) throws Exception {
		Builder builder = RequestConfig.custom();
		if(waitTimeout == null || waitTimeout < 0){
			builder.setSocketTimeout(HttpClientUtil.WAIT_TIMEOUT);
		}else{
			builder.setSocketTimeout(waitTimeout);
		}
		builder.setConnectTimeout(HttpClientUtil.CONNECT_TIMEOUT);
		builder.setConnectionRequestTimeout(HttpClientUtil.CONNECT_REQUEST_TIMEOUT);
		RequestConfig requestConfig = builder.build();
		return HttpClientUtil.sendPost(url, headMap, paraMap, paraBody, requestConfig, fileMap, charset);
	}
	
	
	/**
	 * 发送post请求
	 * @param url 目标地址
	 * @param headMap 请求头map
	 * @param paraMap 请求参数map (参数不能同时使用，如：[如果设置了paraBody,就不能设置其他参数了，如paraMap和fileMap(paraMap和fileMap优先级更高)]     )
	 * @param paraBody 请求内容
	 * @param fileMap 上传的文件map 
	 * @param charset 返回结果及请求结果编码
	 * @return
	 * @throws Exception
	 */
	public static byte[] sendPost(String url,Map<String,String> headMap, Map<String, String> paraMap,String paraBody,Map<String, File> fileMap,String charset) throws Exception {
		Builder builder = RequestConfig.custom();
		builder.setSocketTimeout(HttpClientUtil.WAIT_TIMEOUT);
		builder.setConnectTimeout(HttpClientUtil.CONNECT_TIMEOUT);
		builder.setConnectionRequestTimeout(HttpClientUtil.CONNECT_REQUEST_TIMEOUT);
		RequestConfig requestConfig = builder.build();
		return HttpClientUtil.sendPost(url, headMap, paraMap, paraBody, requestConfig, fileMap, charset);
	}
	
	
	/**
	 * 发送post请求
	 * @param url 目标地址
	 * @param headMap 请求头map
	 * @param paraMap 请求参数map
	 * @param charset 返回结果及请求结果编码
	 * @return
	 * @throws Exception
	 */
	public static byte[] sendPost(String url,Map<String,String> headMap, Map<String, String> paraMap,String charset) throws Exception {
		return HttpClientUtil.sendPost(url, headMap, paraMap, null, null, charset,null);
	}
	
	/**
	 * 发送post请求
	 * @param url 目标地址
	 * @param headMap 请求头map
	 * @param paraMap 请求参数map
	 * @param charset 返回结果及请求结果编码
	 * @param waitTimeout 请求超时毫秒
	 * @return
	 * @throws Exception
	 */
	public static byte[] sendPost(String url,Map<String,String> headMap, Map<String, String> paraMap,String charset,Integer waitTimeout) throws Exception {
		return HttpClientUtil.sendPost(url, headMap, paraMap, null, null, charset,waitTimeout);
	}
	
	
	/**
	 * 发送post请求
	 * @param url 目标地址
	 * @param paraMap 请参数map
	 * @return
	 * @throws Exception
	 */
	public static byte[] sendPost(String url, Map<String, String> paraMap) throws Exception {
		return HttpClientUtil.sendPost(url, null, paraMap, "UTF-8");
	}
	
	
	/**
	 * 发送post请求
	 * @param url 目标地址
	 * @param paraMap 请参数map
	 * @param waitTimeout 请求超时毫秒
	 * @return
	 * @throws Exception
	 */
	public static byte[] sendPost(String url, Map<String, String> paraMap,Integer waitTimeout) throws Exception {
		return HttpClientUtil.sendPost(url, null, paraMap, "UTF-8",waitTimeout);
	}
	
	/**
	 * 发送post请求
	 * @param url 目标地址
	 * @param headMap 请求头map
	 * @param paraBody 请求体内容
	 * @return
	 * @throws Exception
	 */
	public static byte[] sendPost(String url, Map<String,String> headMap, String paraBody) throws Exception {
		return HttpClientUtil.sendPost(url, headMap, null,paraBody,null, "UTF-8",null);
	}
	
	/**
	 * 发送post请求
	 * @param url 目标地址
	 * @param headMap 请求头map
	 * @param paraBody 请求体内容
	 * @param waitTimeout 请求超时毫秒
	 * @return
	 * @throws Exception
	 */
	public static byte[] sendPost(String url, Map<String,String> headMap, String paraBody,Integer waitTimeout) throws Exception {
		return HttpClientUtil.sendPost(url, headMap, null,paraBody,null, "UTF-8",waitTimeout);
	}
	
	
	/**
	 * 发送post请求
	 * @param url 目标地址
	 * @param headMap 请求头map
	 * @param paraBody 请求体内容
	 * @param clazz 返回结果类型
	 * @param charset 返回结果及请求结果编码
	 * @return
	 * @throws Exception
	 */
	public static <T> T sendPostToObj(String url, Map<String,String> headMap, String paraBody,Class<T> clazz,String charset) throws Exception {
		byte[] b = HttpClientUtil.sendPost(url, headMap, null,paraBody,null, charset,null);
		if(b.length == 0){
			return null;
		}
		String json = new String(b,charset);
		return JsonUtil.jsonToObject(json, clazz);
	}
	
	/**
	 * 发送post请求
	 * @param url 目标地址
	 * @param headMap 请求头map
	 * @param paraBody 请求体内容
	 * @param clazz 返回结果类型
	 * @param charset 返回结果及请求结果编码
	 * @param waitTimeout 请求超时毫秒
	 * @return
	 * @throws Exception
	 */
	public static <T> T sendPostToObj(String url, Map<String,String> headMap, String paraBody,Class<T> clazz,String charset,Integer waitTimeout) throws Exception {
		byte[] b = HttpClientUtil.sendPost(url, headMap, null,paraBody,null, charset,waitTimeout);
		if(b.length == 0){
			return null;
		}
		String json = new String(b,charset);
		return JsonUtil.jsonToObject(json, clazz);
	}
	
	
	/**
	 * 发送post请求
	 * @param url 目标地址
	 * @param headMap 请求头map
	 * @param paraMap 请求参数map
	 * @param clazz 返回结果类型
	 * @param charset 返回结果及请求结果编码
	 * @return
	 * @throws Exception
	 */
	public static <T> T sendPostToObj(String url, Map<String,String> headMap,  Map<String,String> paraMap,Class<T> clazz,String charset) throws Exception {
		byte[] b = HttpClientUtil.sendPost(url, headMap, paraMap,null,null, charset,null);
		if(b.length == 0){
			return null;
		}
		String json = new String(b,charset);
		return JsonUtil.jsonToObject(json, clazz);
	}
	

	/**
	 * 发送post请求
	 * @param url 目标地址
	 * @param headMap 请求头map
	 * @param paraMap 请求参数map
	 * @param clazz 返回结果类型
	 * @param charset 返回结果及请求结果编码
	 * @param waitTimeout 请求超时毫秒
	 * @return
	 * @throws Exception
	 */
	public static <T> T sendPostToObj(String url, Map<String,String> headMap,  Map<String,String> paraMap,Class<T> clazz,String charset,Integer waitTimeout) throws Exception {
		byte[] b = HttpClientUtil.sendPost(url, headMap, paraMap,null,null, charset,waitTimeout);
		if(b.length == 0){
			return null;
		}
		String json = new String(b,charset);
		return JsonUtil.jsonToObject(json, clazz);
	}
	
	
	/**
	 * 发送get请求
	 * @param url 目标地址
	 * @param headMap 请求头map
	 * @param paraMap 请求参数map
	 * @param requestConfig 请求配置对象
	 * @param charset 返回结果及请求结果编码
	 * @return
	 * @throws Exception
	 */
	public static byte[] sendGet(String url,Map<String,String> headMap, Map<String, String> paraMap,RequestConfig requestConfig,String charset) throws Exception {
		return HttpClientUtil.basicSend(HttpClientUtil.getHttpClient(), url, HttpClientUtil.GET, headMap, paraMap, null, requestConfig, null, charset);
	}
	
	
	/**
	 * 发送get请求
	 * @param url 目标地址
	 * @param headMap 请求头map
	 * @param paraMap 请求参数map
	 * @param charset 返回结果及请求结果编码
	 * @param waitTimeout 请求超时毫秒
	 * @return
	 * @throws Exception
	 */
	public static byte[] sendGet(String url,Map<String,String> headMap, Map<String, String> paraMap,String charset,Integer waitTimeout) throws Exception {
		Builder builder = RequestConfig.custom();
		if(waitTimeout == null || waitTimeout < 0){
			builder.setSocketTimeout(HttpClientUtil.WAIT_TIMEOUT);
		}else{
			builder.setSocketTimeout(waitTimeout);
		}
		builder.setConnectTimeout(HttpClientUtil.CONNECT_TIMEOUT);
		builder.setConnectionRequestTimeout(HttpClientUtil.CONNECT_REQUEST_TIMEOUT);
		RequestConfig requestConfig = builder.build();
		return HttpClientUtil.sendGet(url, headMap, paraMap, requestConfig, charset);
	}
	
	/**
	 * 发送get请求
	 * @param url 目标地址
	 * @param headMap 请求头map
	 * @param paraMap 请求参数map
	 * @param charset 返回结果及请求结果编码
	 * @return
	 * @throws Exception
	 */
	public static byte[] sendGet(String url,Map<String,String> headMap, Map<String, String> paraMap,String charset) throws Exception {
		Builder builder = RequestConfig.custom();
		builder.setSocketTimeout(HttpClientUtil.WAIT_TIMEOUT);
		builder.setConnectTimeout(HttpClientUtil.CONNECT_TIMEOUT);
		builder.setConnectionRequestTimeout(HttpClientUtil.CONNECT_REQUEST_TIMEOUT);
		RequestConfig requestConfig = builder.build();
		return HttpClientUtil.sendGet(url, headMap, paraMap, requestConfig, charset);
	}

	
	/**
	 * 发送get请求
	 * @param url 目标地址
	 * @param paraMap 请求参数map
	 * @return
	 * @throws Exception
	 */
	public static byte[] sendGet(String url, Map<String, String> paraMap) throws Exception {
		return HttpClientUtil.sendGet(url, null, paraMap, "UTF-8",null);
	}
	
	/**
	 * 发送get请求
	 * @param url 目标地址
	 * @param paraMap 请求参数map
	 * @param waitTimeout 请求超时毫秒
	 * @return
	 * @throws Exception
	 */
	public static byte[] sendGet(String url, Map<String, String> paraMap,Integer waitTimeout) throws Exception {
		return HttpClientUtil.sendGet(url, null, paraMap, "UTF-8",waitTimeout);
	}
	
	
	
	
	/**
	 * 发送get请求
	 * @param url 目标地址
	 * @param headMap 请求头map
	 * @param paraMap 请求参数map
	 * @param clazz	返回结果类型
	 * @param charset 返回结果及请求结果编码
	 * @return
	 * @throws Exception
	 */
	public static <T> T sendGetToObj(String url, Map<String,String> headMap,  Map<String,String> paraMap,Class<T> clazz,String charset) throws Exception {
		byte[] b = HttpClientUtil.sendGet(url, headMap, paraMap, charset,null);
		if(b.length == 0){
			return null;
		}
		String json = new String(b,charset);
		return JsonUtil.jsonToObject(json, clazz);
	}
	
	/**
	 * 发送get请求
	 * @param url 目标地址
	 * @param headMap 请求头map
	 * @param paraMap 请求参数map
	 * @param clazz	返回结果类型
	 * @param charset 返回结果及请求结果编码
	 * @param waitTimeout 请求超时毫秒
	 * @return
	 * @throws Exception
	 */
	public static <T> T sendGetToObj(String url, Map<String,String> headMap,  Map<String,String> paraMap,Class<T> clazz,String charset,Integer waitTimeout) throws Exception {
		byte[] b = HttpClientUtil.sendGet(url, headMap, paraMap, charset,waitTimeout);
		if(b.length == 0){
			return null;
		}
		String json = new String(b,charset);
		return JsonUtil.jsonToObject(json, clazz);
	}
	
}
